package com.sinosoft.dsp.persistence.xml.facade;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.Map;

import javax.faces.bean.ManagedBean;
import javax.faces.bean.NoneScoped;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;

import org.apache.commons.vfs.FileObject;

import com.sinosoft.builder.parser.SinoParser;
import com.sinosoft.builder.parser.SinoParserType;
import com.sinosoft.builder.templates.concept.docStorage.Property;
import com.sinosoft.dsp.system.core.exception.SinoFileException;
import com.sinosoft.dsp.system.core.log.Log;
import com.sinosoft.dsp.system.core.property.OverlayPropertyHandler;
import com.sinosoft.dsp.system.core.vfs.SinoVFSProxy;
import com.sinosoft.dsp.system.core.vfs.VFSParameters;
import com.sinosoft.dsp.system.utils.Const;

/**
 * 文书XML存储的服务门面
 * 
 * @author 潘巍（PeterPan）
 * @since 2011-7-31 下午08:12:56
 * 
 */
@ManagedBean(name = "documentXMLServiceFacade")
@NoneScoped
public class DocumentXMLServiceFacade {

	private static final Log log = Log.getLog(DocumentXMLServiceFacade.class
			.getName());

	public static final VFSParameters VFS_PARAMETERS = new VFSParameters();

	public static final String docPrefix = OverlayPropertyHandler.getInstance()
			.getProperty("vfs.repository.path.document");

	public com.sinosoft.builder.templates.concept.docStorage.Document createDocumentStorageObject(
			String documentId, Map<String, String> props) {
		com.sinosoft.builder.templates.concept.docStorage.Document dt = new com.sinosoft.builder.templates.concept.docStorage.Document();
		dt.setDocumentId(documentId);
		if (props != null) {
			for (Map.Entry<String, String> entry : props.entrySet()) {
				if (!Const.isEmpty(entry.getKey())) {
					Property pt = new Property();
					pt.setName(entry.getKey());
					pt.setColeValueRef(entry.getValue());
					dt.getProperty().add(pt);
				}

			}
		}
		return dt;
	}

	public Map<String, String> createDocumentStoragePropertiesMap(
			com.sinosoft.builder.templates.concept.docStorage.Document doc) {
		Map<String, String> props = new HashMap<String, String>();
		if (doc != null) {
			for (Property prop : doc.getProperty()) {
				props.put(prop.getName(), prop.getColeValueRef());
			}
		}
		return props;
	}

	/**
	 * 通过路径和文件名获得文书存储对象
	 * 
	 * @param fileName
	 * @param filePath
	 * @return
	 */
	public com.sinosoft.builder.templates.concept.docStorage.Document getDocumentStorageObject(
			String fileName, String filePath) {
		FileObject fo = null;
		InputStream is = null;
		try {
			// 获得解析器
			SinoParser<com.sinosoft.builder.templates.concept.docStorage.Document> parser = new SinoParser<com.sinosoft.builder.templates.concept.docStorage.Document>();
			Unmarshaller unmarshaller = parser
					.getUnmarshaller(SinoParserType.DOCUMENT_STORAGE);

			// 获得存储的文件对象
			String path = docPrefix + "/" + filePath;
			fo = SinoVFSProxy.getInstance().getFileObject(VFS_PARAMETERS, path,
					fileName);
			if (!fo.exists()) {
				throw new SinoFileException("无法获得文件，路径：" + path + "，文件名："
						+ fileName);
			}

			// 存储
			is = fo.getContent().getInputStream();
			return (com.sinosoft.builder.templates.concept.docStorage.Document) unmarshaller
					.unmarshal(is);

		} catch (SinoFileException e) {
			log.error("获得存储的文件对象出现错误。");
		} catch (Exception e) {
			log.error("获得存储的文件对象出现错误。");
		} finally {
			if (is != null) {
				try {
					is.close();
				} catch (IOException e) {
					log.error("获得存储的文件对象出现错误。");
				}
			}
			SinoVFSProxy.getInstance().closeFileObject(fo);
		}
		return null;
	}

	/**
	 * 创建文书文件
	 * 
	 * @param fileName
	 * @param filePath
	 * @param dt
	 */
	public void createFile(String fileName, String filePath,
			com.sinosoft.builder.templates.concept.docStorage.Document dt) {
		FileObject fo = null;
		OutputStream os = null;
		try {
			// 获得解析器
			SinoParser<com.sinosoft.builder.templates.concept.docStorage.Document> parser = new SinoParser<com.sinosoft.builder.templates.concept.docStorage.Document>();
			Marshaller marshaller = parser
					.getMarshaller(SinoParserType.DOCUMENT_STORAGE);

			// 获得存储的文件对象
			String path = docPrefix + "/" + filePath;
			fo = SinoVFSProxy.getInstance().getFileObject(VFS_PARAMETERS, path,
					fileName);
			if (fo.exists()) {
				throw new SinoFileException("所要创建的文件已经存在，路径：" + path + "，文件名："
						+ fileName);
			}

			// 存储
			os = fo.getContent().getOutputStream();
			marshaller.marshal(dt, os);

		} catch (SinoFileException e) {
			log.error("获得存储的文件对象出现错误。");
		} catch (Exception e) {
			log.error("存储的文件对象出现错误。");
		} finally {
			if (os != null) {
				try {
					os.close();
				} catch (IOException e) {
					log.error("存储的文件对象出现错误。");
				}
			}
			SinoVFSProxy.getInstance().closeFileObject(fo);
		}
	}

	/**
	 * 修改文书
	 * 
	 * @param fileName
	 * @param filePath
	 * @param dt
	 */
	public void editFile(String fileName, String filePath,
			com.sinosoft.builder.templates.concept.docStorage.Document dt) {
		FileObject fo = null;
		OutputStream os = null;
		try {
			// 获得存储的文件对象
			String path = docPrefix + "/" + filePath;
			fo = SinoVFSProxy.getInstance().getFileObject(VFS_PARAMETERS, path,
					fileName);
			if (fo.exists()) {
				fo.delete();
			}
			do {
			} while (fo.exists());
			createFile(fileName, filePath, dt);
		} catch (SinoFileException e) {
			log.error("获得存储的文件对象出现错误。");
		} catch (Exception e) {
			log.error("存储的文件对象出现错误。");
		} finally {
			if (os != null) {
				try {
					os.close();
				} catch (IOException e) {
					log.error("存储的文件对象出现错误。");
				}
			}
			SinoVFSProxy.getInstance().closeFileObject(fo);
		}
	}

	/**
	 * 删除文书
	 * 
	 * @param fileName
	 * @param filePath
	 */
	public void deleteFile(String fileName, String filePath) {
		FileObject fo = null;
		OutputStream os = null;
		try {
			// 获得存储的文件对象
			String path = docPrefix + "/" + filePath;
			fo = SinoVFSProxy.getInstance().getFileObject(VFS_PARAMETERS, path,
					fileName);
			if (fo.exists()) {
				fo.delete();
			}
		} catch (SinoFileException e) {
			log.error("获得存储的文件对象出现错误。");
		} catch (Exception e) {
			log.error("存储的文件对象出现错误。");
		} finally {
			if (os != null) {
				try {
					os.close();
				} catch (IOException e) {
					log.error("存储的文件对象出现错误。");
				}
			}
			SinoVFSProxy.getInstance().closeFileObject(fo);
		}
	}
}
